#ifndef GAMEENGINE_GEOMETRY_COORDINATESYSTEMS_TRANSFORMER3D_ORIENTATION_H
#define GAMEENGINE_GEOMETRY_COORDINATESYSTEMS_TRANSFORMER3D_ORIENTATION_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/vector3d.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

template <class T> class Quaternion;

namespace Transformer3DOrientation {
	//! Index in the 3x3 matrix of a three-dimensional transformer
	enum Index {
		//! First index
		First = 0,
		//! Second index
		Second = 1,
		//! Third index
		Third = 2
	};
}

//! Class used to transform orientations between two 3D coordinate systems
/*!
 *  This class is a wrapper to a three-dimensional rotation matrix. It provides convenience
 *  functions that allow to build the rotation matrix from orientations that are known both
 *  in the source and in the destination spaces.
 *
 @sa Class Transformer2dOrientation for transformation of 2D orientations and class
     Transformer3d for 3D transformations of spatial coordinates.
 @note Most algorithms expect floating point operations.
       Type T should therefore not be an integer type
 */
template <class T>
class Transformer3dOrientation {
	//! The quaternion class is friend of the transformer class to enable direct access to the transformation matrix
	friend class Quaternion<T>;

public:
	Transformer3dOrientation();
	Transformer3dOrientation(const Vector3d<T>& from1, const Vector3d<T>& from2, const Vector3d<T>& from3,
		const Vector3d<T>& to1, const Vector3d<T>& to2, const Vector3d<T>& to3);
	Transformer3dOrientation(const Transformer3dOrientation& rhs);
	virtual ~Transformer3dOrientation();
	Transformer3dOrientation& operator=(const Transformer3dOrientation& rhs);

	bool set_transformation(const Vector3d<T>& from1, const Vector3d<T>& from2, const Vector3d<T>& from3,
		const Vector3d<T>& to1, const Vector3d<T>& to2, const Vector3d<T>& to3);

	Vector3d<T> column1() const;
	Vector3d<T> column2() const;
	Vector3d<T> column3() const;
	Vector3d<T> row1() const;
	Vector3d<T> row2() const;
	Vector3d<T> row3() const;

	T matrix(Transformer3DOrientation::Index row, Transformer3DOrientation::Index column) const;
	T& matrix(Transformer3DOrientation::Index row, Transformer3DOrientation::Index column);

	Vector3d<T> transform(const Vector3d<T>& from) const;

	Transformer3dOrientation inverse(bool* ok = nil) const;

protected:
	//! Transformation matrix
	T matrix_[3][3];
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/CoordinateSystems/transformer3d_orientation.hpp>

#endif
